#!/bin/bash
# ==============================================================================
# Julia Installation Script
# ==============================================================================
# This script installs Julia to ~/usr/julia and creates a symlink at ~/bin/julia

set -e

# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'

# Default configuration
JULIA_INSTALL_DIR="$HOME/usr/julia"
JULIA_SYMLINK="$HOME/bin/julia"
JULIA_VERSION="1.10.4"
JULIA_ARCH="linux-x86_64"
JULIA_URL_BASE="https://julialang-s3.julialang.org/bin/linux/x64"
FORCE_INSTALL="false"
VERBOSE="false"
SKIP_SYMLINK="false"
CUSTOM_SOURCE=""

print_banner() {
    echo -e "${CYAN}================================================${NC}"
    echo -e "${CYAN}      Julia Installation Script${NC}"
    echo -e "${CYAN}================================================${NC}"
    echo "🚀 Installing Julia to custom location"
    echo ""
    echo "📁 Installation Directory: $JULIA_INSTALL_DIR"
    echo "🔗 Symlink Location: $JULIA_SYMLINK"
    echo "📦 Julia Version: $JULIA_VERSION"
    echo "💻 Architecture: $JULIA_ARCH"
    echo ""
}

print_usage() {
    echo "Usage: $0 [OPTIONS]"
    echo ""
    echo "OPTIONS:"
    echo "  -h, --help         - Show this help message"
    echo "  -v, --verbose      - Verbose output"
    echo "  -f, --force        - Force reinstallation (delete existing)"
    echo "  -s, --source PATH  - Install from local tar.gz file"
    echo "  --version VERSION  - Julia version to install (default: $JULIA_VERSION)"
    echo "  --arch ARCH        - Architecture (default: $JULIA_ARCH)"
    echo "  --no-symlink       - Skip creating ~/bin/julia symlink"
    echo "  --install-dir DIR  - Custom installation directory"
    echo ""
    echo "EXAMPLES:"
    echo "  $0                                    # Install Julia $JULIA_VERSION"
    echo "  $0 --force                           # Force reinstall"
    echo "  $0 --version 1.9.4                  # Install specific version"
    echo "  $0 -s ~/Downloads/julia-1.10.4.tar.gz # Install from local file"
    echo ""
}

check_existing_installation() {
    local skip_install=false

    # Check if symlink exists and is working
    if [[ -L "$JULIA_SYMLINK" && -x "$JULIA_SYMLINK" ]]; then
        local existing_version=$("$JULIA_SYMLINK" --version 2>/dev/null | cut -d' ' -f3 || echo "unknown")

        if [[ "$FORCE_INSTALL" == "true" ]]; then
            echo -e "${YELLOW}⚠️ Found existing Julia ($existing_version) - will reinstall due to --force${NC}"
        else
            echo -e "${GREEN}✓ Julia already installed: version $existing_version${NC}"
            echo "Location: $JULIA_SYMLINK -> $(readlink "$JULIA_SYMLINK" 2>/dev/null || echo "unknown")"
            echo ""
            echo "Use --force to reinstall or --help for more options"
            skip_install=true
        fi
    fi

    # Check installation directory
    if [[ -d "$JULIA_INSTALL_DIR" ]]; then
        if [[ "$FORCE_INSTALL" == "true" ]]; then
            echo -e "${YELLOW}🗑️ Removing existing installation directory...${NC}"
            rm -rf "$JULIA_INSTALL_DIR"
        elif [[ "$skip_install" == "false" ]]; then
            echo -e "${YELLOW}⚠️ Installation directory exists: $JULIA_INSTALL_DIR${NC}"
            echo "Use --force to overwrite"
            skip_install=true
        fi
    fi

    if [[ "$skip_install" == "true" ]]; then
        exit 0
    fi
}

download_julia() {
    local julia_filename="julia-${JULIA_VERSION}-${JULIA_ARCH}.tar.gz"
    local julia_url="${JULIA_URL_BASE}/${JULIA_VERSION%.*}/${julia_filename}"
    local download_path="/tmp/$julia_filename"

    echo -e "${BLUE}📥 Downloading Julia $JULIA_VERSION...${NC}"
    echo "URL: $julia_url"

    if command -v wget >/dev/null 2>&1; then
        if [[ "$VERBOSE" == "true" ]]; then
            wget -O "$download_path" "$julia_url"
        else
            wget -q --show-progress -O "$download_path" "$julia_url"
        fi
    elif command -v curl >/dev/null 2>&1; then
        if [[ "$VERBOSE" == "true" ]]; then
            curl -L -o "$download_path" "$julia_url"
        else
            curl -L --progress-bar -o "$download_path" "$julia_url"
        fi
    else
        echo -e "${RED}❌ ERROR: Neither wget nor curl found${NC}" >&2
        exit 1
    fi

    if [[ ! -f "$download_path" ]]; then
        echo -e "${RED}❌ ERROR: Download failed${NC}" >&2
        exit 1
    fi

    echo "$download_path"
}

verify_julia_archive() {
    local archive_path="$1"

    echo -e "${BLUE}🔍 Verifying Julia archive...${NC}"

    # Check if it's a valid tar.gz file
    if ! tar -tzf "$archive_path" >/dev/null 2>&1; then
        echo -e "${RED}❌ ERROR: Invalid tar.gz archive${NC}" >&2
        return 1
    fi

    # Check if it contains julia binary
    if ! tar -tzf "$archive_path" | grep -q "bin/julia$"; then
        echo -e "${RED}❌ ERROR: Archive doesn't contain julia binary${NC}" >&2
        return 1
    fi

    echo -e "${GREEN}✓ Archive verified${NC}"
    return 0
}

install_julia() {
    local archive_path="$1"
    local temp_dir=$(mktemp -d)

    echo -e "${BLUE}📦 Installing Julia...${NC}"

    # Extract to temporary directory
    echo "Extracting to temporary location..."
    if [[ "$VERBOSE" == "true" ]]; then
        tar -xzf "$archive_path" -C "$temp_dir"
    else
        tar -xzf "$archive_path" -C "$temp_dir" 2>/dev/null
    fi

    # Find the extracted directory (usually julia-x.x.x)
    local extracted_dir=$(find "$temp_dir" -maxdepth 1 -type d -name "julia-*" | head -1)

    if [[ -z "$extracted_dir" ]]; then
        echo -e "${RED}❌ ERROR: Could not find extracted Julia directory${NC}" >&2
        rm -rf "$temp_dir"
        exit 1
    fi

    # Create parent directory if needed
    mkdir -p "$(dirname "$JULIA_INSTALL_DIR")"

    # Move to final location
    echo "Installing to: $JULIA_INSTALL_DIR"
    mv "$extracted_dir" "$JULIA_INSTALL_DIR"

    # Clean up
    rm -rf "$temp_dir"

    # Verify installation
    if [[ -x "$JULIA_INSTALL_DIR/bin/julia" ]]; then
        local installed_version=$("$JULIA_INSTALL_DIR/bin/julia" --version | cut -d' ' -f3)
        echo -e "${GREEN}✓ Julia $installed_version installed successfully${NC}"
    else
        echo -e "${RED}❌ ERROR: Julia binary not found after installation${NC}" >&2
        exit 1
    fi
}

create_symlink() {
    if [[ "$SKIP_SYMLINK" == "true" ]]; then
        echo -e "${YELLOW}⚠️ Skipping symlink creation${NC}"
        return 0
    fi

    echo -e "${BLUE}🔗 Creating symlink...${NC}"

    # Create ~/bin directory if it doesn't exist
    mkdir -p "$(dirname "$JULIA_SYMLINK")"

    # Remove existing symlink if it exists
    if [[ -L "$JULIA_SYMLINK" ]]; then
        rm "$JULIA_SYMLINK"
    fi

    # Create new symlink
    ln -s "$JULIA_INSTALL_DIR/bin/julia" "$JULIA_SYMLINK"

    if [[ -x "$JULIA_SYMLINK" ]]; then
        echo -e "${GREEN}✓ Symlink created: $JULIA_SYMLINK -> $JULIA_INSTALL_DIR/bin/julia${NC}"

        # Check if ~/bin is in PATH
        if [[ ":$PATH:" != *":$HOME/bin:"* ]]; then
            echo -e "${YELLOW}💡 NOTE: $HOME/bin is not in your PATH${NC}"
            echo "Add this to your ~/.bashrc or ~/.profile:"
            echo "    export PATH=\"\$HOME/bin:\$PATH\""
        fi
    else
        echo -e "${RED}❌ ERROR: Symlink creation failed${NC}" >&2
        exit 1
    fi
}

test_installation() {
    echo -e "${BLUE}🧪 Testing installation...${NC}"

    local test_binary="$JULIA_INSTALL_DIR/bin/julia"
    if [[ "$SKIP_SYMLINK" == "false" && -x "$JULIA_SYMLINK" ]]; then
        test_binary="$JULIA_SYMLINK"
    fi

    echo "Testing Julia binary: $test_binary"

    # Test version
    local version_output=$("$test_binary" --version 2>&1)
    echo "Version: $version_output"

    # Test basic functionality
    echo -n "Testing basic functionality: "
    if echo 'println("Hello, Julia!")' | "$test_binary" -q >/dev/null 2>&1; then
        echo -e "${GREEN}✓ PASSED${NC}"
    else
        echo -e "${RED}❌ FAILED${NC}"
        return 1
    fi

    # Test package manager
    echo -n "Testing package manager: "
    if echo 'using Pkg; println("Pkg OK")' | "$test_binary" -q >/dev/null 2>&1; then
        echo -e "${GREEN}✓ PASSED${NC}"
    else
        echo -e "${YELLOW}⚠️ WARNING: Package manager test failed${NC}"
    fi

    echo -e "${GREEN}✅ Installation test completed${NC}"
}

print_summary() {
    echo ""
    echo -e "${GREEN}================================================${NC}"
    echo -e "${GREEN}   Julia Installation Completed Successfully!${NC}"
    echo -e "${GREEN}================================================${NC}"
    echo ""
    echo "📁 Installation Directory: $JULIA_INSTALL_DIR"
    if [[ "$SKIP_SYMLINK" == "false" ]]; then
        echo "🔗 Symlink: $JULIA_SYMLINK"
    fi

    local julia_version=$("$JULIA_INSTALL_DIR/bin/julia" --version | cut -d' ' -f3)
    echo "📦 Julia Version: $julia_version"
    echo ""
    echo "🚀 Usage:"
    if [[ "$SKIP_SYMLINK" == "false" ]]; then
        echo "  ~/bin/julia --version"
        echo "  ~/bin/julia"
    else
        echo "  $JULIA_INSTALL_DIR/bin/julia --version"
        echo "  $JULIA_INSTALL_DIR/bin/julia"
    fi
    echo ""
    echo "📚 Next Steps:"
    echo "  • Add ~/bin to your PATH if not already there"
    echo "  • Test with: julia --version"
    echo "  • Start Julia REPL with: julia"
    echo ""
}

# ==============================================================================
# MAIN SCRIPT
# ==============================================================================

# Parse command line arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help)
            print_usage
            exit 0
            ;;
        -v|--verbose)
            VERBOSE="true"
            shift
            ;;
        -f|--force)
            FORCE_INSTALL="true"
            shift
            ;;
        -s|--source)
            CUSTOM_SOURCE="$2"
            shift 2
            ;;
        --version)
            JULIA_VERSION="$2"
            shift 2
            ;;
        --arch)
            JULIA_ARCH="$2"
            shift 2
            ;;
        --no-symlink)
            SKIP_SYMLINK="true"
            shift
            ;;
        --install-dir)
            JULIA_INSTALL_DIR="$2"
            shift 2
            ;;
        *)
            echo -e "${RED}ERROR: Unknown option: $1${NC}" >&2
            print_usage
            exit 1
            ;;
    esac
done

# Main execution
print_banner

# Check for existing installation
check_existing_installation

# Determine archive source
archive_path=""
if [[ -n "$CUSTOM_SOURCE" ]]; then
    if [[ ! -f "$CUSTOM_SOURCE" ]]; then
        echo -e "${RED}❌ ERROR: Source file not found: $CUSTOM_SOURCE${NC}" >&2
        exit 1
    fi
    archive_path="$CUSTOM_SOURCE"
    echo -e "${BLUE}📁 Using local file: $archive_path${NC}"
else
    archive_path=$(download_julia)
fi

# Verify and install
if verify_julia_archive "$archive_path"; then
    install_julia "$archive_path"
    create_symlink
    test_installation
    print_summary

    # Clean up downloaded file if we downloaded it
    if [[ -z "$CUSTOM_SOURCE" && -f "$archive_path" ]]; then
        rm -f "$archive_path"
    fi
else
    echo -e "${RED}❌ Installation failed due to archive verification errors${NC}" >&2
    exit 1
fi

echo -e "${GREEN}🎉 Julia installation completed successfully!${NC}"